package logger

import (
	"fmt"
	"io"
	"os"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

// var (
// 	Logger      *zap.Logger
// 	SugarLogger *zap.SugaredLogger
// )

type Level = zapcore.Level

const (
	DebugLevel = zapcore.DebugLevel
	InfoLevel  = zapcore.InfoLevel
	WarnLevel  = zapcore.WarnLevel
	ErrorLevel = zapcore.ErrorLevel
	PanicLevel = zapcore.PanicLevel
	FatalLevel = zapcore.FatalLevel
)

type Logger struct {
	l  *zap.Logger
	al *zap.AtomicLevel
}

func New(env string, out io.Writer, level Level) *Logger {
	if out == nil {
		out = os.Stderr
	}

	al := zap.NewAtomicLevelAt(level)
	l := InitLogger(env, al)
	return &Logger{
		l:  l,
		al: &al,
	}
}

func InitLogger(env string, level zap.AtomicLevel) *zap.Logger {
	config := NewProductionConfig(env, level)
	logger, err := config.Build(
		zap.AddCaller(),      // 添加调用者信息
		zap.AddCallerSkip(1)) // 跳过一层调用栈（mylog包本身的封装）)

	if err != nil {
		fmt.Printf("初始化日志失败: %v\n", err)
		return zap.NewExample()
	}

	return logger
}

func NewProductionConfig(env string, level zap.AtomicLevel) zap.Config {
	var config zap.Config
	switch env {
	case "production":
		config = zap.Config{
			Level:       level,
			Development: false,
			Sampling: &zap.SamplingConfig{
				Initial:    100,
				Thereafter: 100,
			},
			Encoding:         "json",
			EncoderConfig:    zap.NewProductionEncoderConfig(),
			OutputPaths:      []string{"stdout"},
			ErrorOutputPaths: []string{"stderr"},
		}
	default:
		config = zap.Config{
			Level:            level,
			Development:      true,
			Encoding:         "console",
			EncoderConfig:    zap.NewDevelopmentEncoderConfig(),
			OutputPaths:      []string{"stdout"},
			ErrorOutputPaths: []string{"stderr"},
		}
	}

	return config
}

func (l *Logger) SetLevel(level Level) {
	if l.al != nil {
		l.al.SetLevel(level)
	}
}

type Field = zapcore.Field

func (l *Logger) Print(v ...interface{}) {
	l.l.Sugar().Info(v...)
}

func (l *Logger) Printf(format string, v ...interface{}) {
	l.l.Sugar().Infof(format, v...)
}

func (l *Logger) Println(v ...interface{}) {
	l.l.Sugar().Info(v...)
}

func (l *Logger) Fatal(v ...interface{}) {
	l.l.Sugar().Fatal(v...)
}

func (l *Logger) Fatalf(format string, v ...interface{}) {
	l.l.Sugar().Fatalf(format, v...)
}

func (l *Logger) Debug(v ...interface{}) {
	l.l.Sugar().Debug(v...)
}

func (l *Logger) Debugf(format string, v ...interface{}) {
	l.l.Sugar().Debugf(format, v...)
}

func (l *Logger) Info(v ...interface{}) {
	l.l.Sugar().Info(v...)
}

func (l *Logger) Infof(format string, v ...interface{}) {
	l.l.Sugar().Infof(format, v...)
}

func (l *Logger) Warn(v ...interface{}) {
	l.l.Sugar().Warn(v...)
}

func (l *Logger) Warnf(format string, v ...interface{}) {
	l.l.Sugar().Warnf(format, v...)
}

func (l *Logger) Error(v ...interface{}) {
	l.l.Sugar().Error(v...)
}

func (l *Logger) Errorf(format string, v ...interface{}) {
	l.l.Sugar().Errorf(format, v...)
}

func (l *Logger) Panic(v ...interface{}) {
	l.l.Sugar().Panic(v...)
}

var std = New("production", os.Stderr, InfoLevel)

func Default() *Logger         { return std }
func ReplaceDefault(l *Logger) { std = l }

func SetLevel(level Level) {
	std.SetLevel(level)
}

func Print(v ...interface{}) {
	std.Print(v...)
}

func Printf(format string, v ...interface{}) {
	std.Printf(format, v...)
}

func Println(v ...interface{}) {
	std.Println(v...)
}

func Fatal(v ...interface{}) {
	std.Fatal(v...)
}

func Fatalf(format string, v ...interface{}) {
	std.Fatalf(format, v...)
}

func Debug(v ...interface{}) {
	std.Debug(v...)
}

func Debugf(format string, v ...interface{}) {
	std.Debugf(format, v)
}

func Info(v ...interface{}) {
	std.Info(v)
}

func Infof(format string, v ...interface{}) {
	std.Infof(format, v...)
}

func Warn(v ...interface{}) {
	std.Warn(v...)
}

func Warnf(format string, v ...interface{}) {
	std.Warnf(format, v...)
}

func Error(v ...interface{}) {
	std.Error(v...)
}

func Errorf(format string, v ...interface{}) {
	std.Errorf(format, v...)
}

func Panic(v ...interface{}) {
	std.Panic(v...)
}
